/**
 * =====================================================================================
 *       @file  ngx_cycle.c
 *      @brief  
 *
 *  Detailed description starts here.
 *
 *   @internal
 *     Created  2012年05月08日 21时50分23秒 
 *    Revision  1.0.0.0
 *    Compiler  gcc/g++
 *
 *     @author  luis
 * =====================================================================================
 */

#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include "ngx_cycle.h"
#include "ngx_palloc.h"
#include "ngx_core.h"
#include "ngx_conf_file.h"
#include "ngx_connection.h"

extern ngx_module_t *ngx_modules[];
extern void ngx_init_connection(ngx_connection_t *c);

volatile ngx_cycle_t *ngx_cycle;

ngx_cycle_t *ngx_init_cycle()
{
    ngx_uint_t           i;
    ngx_cycle_t         *cycle; 
    ngx_pool_t          *pool;
    ngx_uint_t           n;
    ngx_listening_t     *listening;
    struct sockaddr_in  *addr;
    
    pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE);
    if (pool == NULL)
    {
        return NULL;
    } 

    cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
    if (cycle == NULL)
    {
        perror("malloc cycle");
        return NULL;
    }
    cycle->pool = pool;

    n = 10;     //or old_cycle->listening.nelts
    cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
    if (cycle->listening.elts == NULL)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }
    
    cycle->listening.nelts = 0;
    cycle->listening.size = sizeof(ngx_listening_t);
    cycle->listening.nalloc = n;
    cycle->listening.pool = pool; 
    
    //XXX constant listeng addr
    cycle->listening.nelts = 1; 
    listening = (ngx_listening_t *)cycle->listening.elts;
    listening->fd = -1;
    listening->backlog = 100;
    listening->type = SOCK_STREAM;
    listening->socklen = sizeof(struct sockaddr);
    listening->handler = ngx_init_connection;

    listening->sockaddr = ngx_pcalloc(pool, sizeof(struct sockaddr));
    if (listening->sockaddr == NULL)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

    addr = (struct sockaddr_in *)listening->sockaddr;
    addr->sin_family = AF_INET;
    addr->sin_port = htons(80);
    addr->sin_addr.s_addr = htonl(INADDR_ANY);

    if (ngx_open_listening_sockets(cycle) != NGX_OK)
    {
        ngx_destroy_pool(pool);
        perror("open listening sockets");
        return NULL; 
    } 

    cycle->connection_n = 5;

    //init all module
    for (i = 0; ngx_modules[i]; ++i)
    {
        if (ngx_modules[i]->init_module)
        {
            if (ngx_modules[i]->init_module(cycle) != NGX_OK)
            {
                perror("init module");
                exit(1);
            }
        }
    }

    return cycle;
}
